/*
    This file is part of SisIB - Sistema de Identificação Biométrica.

    Copyright (C) 2014  Thiago Azevedo Alves.

    SisIB is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    SisIB is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with SisIB.  If not, see <http://www.gnu.org/licenses/>.
 */

package sisib;

import com.griaule.grfingerjava.FingerprintImage;
import com.griaule.grfingerjava.GrFingerJava;
import com.griaule.grfingerjava.GrFingerJavaException;
import com.griaule.grfingerjava.IFingerEventListener;
import com.griaule.grfingerjava.IImageEventListener;
import com.griaule.grfingerjava.IStatusEventListener;
import com.griaule.grfingerjava.MatchingContext;
import com.griaule.grfingerjava.Template;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriter;
import javax.imageio.spi.ImageWriterSpi;
import javax.imageio.stream.ImageOutputStream;
import javax.swing.JOptionPane;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.view.JasperViewer;
import static sisib.Splash.tr;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.xml.JRXmlLoader;
//import static sisib.Splash.tr;

/**
 *
 * @author Thiago Azevedo Alves
 */

public class Util implements IStatusEventListener, IImageEventListener, IFingerEventListener{
    //banco de dados;
    public Database db;
    //impressao digital;
    public FingerprintImage fingerprint;
    //dados recolhidos da impressao digital;
    public Template template;
    //Vetor de todos os dados de impressoes encontrados no banco de dados;
    private Vector templateVector;
    //atributo utilizado no reconhecimento de digitais(se duas digitais são identicas);
    private MatchingContext matchContext = null;
    //booleano que indica inicialização de captura;
    private boolean captureInitalized = false;
    //inteiro indicador do ID do evento;
    int evt;
    
    public Util() throws SQLException{
        evt = 1; //cadastro
        db = new Database();
        db.connect();
        Vector temp = null;
        int i = db.getLenght();
        
        if(i> 0){
            temp = db.getTemplateVector();
            templateVector = new Vector(temp);
        }else{
            templateVector = new Vector();
            JOptionPane.showMessageDialog(null, "Nenhum Template encontrado no banco de dados.");
        }
        template = new Template();
    }
    
    public void setEvt(int e){
        evt=e;
    }
    
    public void start() throws IOException {
        try {
            // Initializing GrCapture.
            matchContext = new MatchingContext();
            GrFingerJava.initializeCapture(this);
            captureInitalized = true;
        }catch (GrFingerJavaException e) {
            JOptionPane.showMessageDialog(null, e.toString());
        }
    }
    
    
    
    // This function is called every time a fingerprint reader is plugged.
    
    public void onSensorPlug(String idSensor){
        try {
            // Start capturing from plugged sensor.
            GrFingerJava.startCapture(idSensor, this, this);
        } catch (GrFingerJavaException e) {
            JOptionPane.showMessageDialog(null, e.toString());
        }
    }
    
    // This function is called every time a fingerprint reader is plugged.
    
    public void onSensorUnplug(String idSensor){
        try {
            JOptionPane.showMessageDialog(null, "Sensor: " + idSensor + ". Evento: Desligado.");
            // Start capturing from plugged sensor.
            GrFingerJava.stopCapture(idSensor);
        } catch (GrFingerJavaException e) {
            JOptionPane.showMessageDialog(null, e.toString());
        }
    }
    
    public void onImageAcquired(String idSensor, FingerprintImage fingerprint) {
        processImage(fingerprint);
    }
    
    // This function processes a fingerprint image
    private void processImage(FingerprintImage fingerprint) {
        this.fingerprint = fingerprint;;
        extract();
    }
    
    // Add a fingerprint template to database
    public void enroll(int id, String nome, String unimed, byte[] b) throws SQLException {
        // Adds template to database and gets the ID.
        int iden;
        iden = identify();
        if( iden < 0){
            int i = templateVector.size();
            templateVector.add(i, template);
            JOptionPane.showMessageDialog(null, "Digital registrada com a id: " + Integer.toString(id));
            
            
            db.Salva(id, nome, unimed, b);
        }else{
            JOptionPane.showMessageDialog(null, "Impossível realizar cadastro, digital já cadastrada.");
        }
    }

    //Modificar modo de identificação acessando a nova tabela criada cad_func;
    
    public int identify() throws SQLException {
        try {
            
            // Starting identification process and supplying query template.
            matchContext.prepareForIdentification(template);
            
            db.preparedStatement = db.conn.prepareStatement("select * from func");
            db.resultSet = db.preparedStatement.executeQuery();
                
            int i = 0;
            while (db.resultSet.next()) {
                // Create a new Template
                Template referenceTemplate = new Template(db.resultSet.getBytes("temp"));
                // Comparing current template.
                boolean doesMatched = matchContext.identify(referenceTemplate);
                // Checking if query template and reference template match.
                if (doesMatched) {
                    db.acessa(db.resultSet.getString("nome"), evt);
                    return i;
                }
                i++;
            }
            //se i=1 o programa encontrou usuários mas não bateu com a digital
            if(i == 1){
                return -1;
            }
            
        } catch (GrFingerJavaException e) {
            // write error to log
            JOptionPane.showMessageDialog(null, e.getMessage());
        }
        //caso chegue até aqui nenhum usuário foi encontrado na tabela
        return -1;
    }
      
    
    // Extract a fingerprint template from current image
    public void extract() {
        try {
            template = matchContext.extract(fingerprint);
            String msg = "Template extraido com sucesso. Qualidade : ";
            switch (template.getQuality()) {
                case Template.HIGH_QUALITY:
                    msg += "Alta.";
                    break;
                case Template.MEDIUM_QUALITY:
                    msg += "Media.";
                    break;
                case Template.LOW_QUALITY:
                    msg += "Baixa.";
                    break;
                }
            JOptionPane.showMessageDialog(null, msg);
            //ui.showImage(GrFingerJava.getBiometricImage(template, fingerprint));
        } catch (GrFingerJavaException e) {
            JOptionPane.showMessageDialog(null, e.toString());
        }
        int i = 0;
        try {
            i = tr.tc.u.identify();
            if (i < 0){
                JOptionPane.showMessageDialog(null, "Participante não cadastrado.");
            }else{
                JOptionPane.showMessageDialog(null, "Participante: | " + tr.tc.u.db.getNome(i) +
                    "\nId:                     | " + Integer.toString(tr.tc.u.db.getId(i)) +
                    "\nUnimed:          | " + tr.tc.u.db.getUnimed(i));
            }
        } catch (SQLException ex) {
            Logger.getLogger(TelaCad.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    public void saveToFile(File file, ImageWriterSpi spi) {
        // Save image.
        try {
            ImageWriter writer = spi.createWriterInstance(this);
            ImageOutputStream output = ImageIO.createImageOutputStream(file);
            writer.setOutput(output);
            writer.write(this.getFingerprint());
            output.close();
            writer.dispose();
        }catch (IOException e) {
            // write error to log
            e.printStackTrace();
        }
    }

    @Override
    public void onFingerDown(String string) {   
        //printLog("Sensor em uso.");
    }

    @Override
    public void onFingerUp(String string) {
        //printLog("Sensor em espera.");
    }
    
    public RenderedImage getFingerprint() {
        return fingerprint;
    }
    
    public void stop() {
        try {
            if (matchContext != null) {
                matchContext.destroy();
                matchContext = null;
            }
            if (captureInitalized) {
                GrFingerJava.finalizeCapture();
                captureInitalized = false;
            }
        } catch (GrFingerJavaException e) {
            JOptionPane.showMessageDialog(null, e.toString());
        }
    }

    public void abrirReportCad() throws JRException, SQLException {  
        Map parameters = new HashMap();
        JasperDesign jd = JRXmlLoader.load("C:\\Users\\Thiago\\Documents\\NetBeans Projects\\SisIB\\src\\sisib\\reportCad.jrxml");
        JasperReport jr = JasperCompileManager.compileReport(jd);  
        JasperPrint jp = JasperFillManager.fillReport("C:\\Users\\Thiago\\Documents\\NetBeans Projects\\SisIB\\src\\sisib\\reportCad.jasper", parameters, db.conn);  
        JasperViewer jrviewer = new JasperViewer(jp);  
        jrviewer.setVisible(true);
    }
    
    public void abrirReportNCad() throws JRException, SQLException {  
        Map parameters = new HashMap();
        JasperDesign jd = JRXmlLoader.load("C:\\Users\\Thiago\\Documents\\NetBeans Projects\\SisIB\\src\\sisib\\reportNCad.jrxml");
        JasperReport jr = JasperCompileManager.compileReport(jd);  
        JasperPrint jp = JasperFillManager.fillReport("C:\\Users\\Thiago\\Documents\\NetBeans Projects\\SisIB\\src\\sisib\\reportNCad.jasper", parameters, db.conn);  
        JasperViewer jrviewer = new JasperViewer(jp);  
        jrviewer.setVisible(true);
    }
}
    